package com.bolt.support.spring.jpa.handler;


import com.bolt.common.utils.StrUtil;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.*;
import javax.lang.model.util.ElementFilter;
import javax.persistence.Column;
import java.util.List;

public class QueryBuildScanner {

    private ProcessingEnvironment processingEnv;

    public QueryBuildScanner(ProcessingEnvironment processingEnv) {
        this.processingEnv = processingEnv;
    }

    private TypeMirror normalize(TypeMirror type) {
        if (type.getKind() == TypeKind.TYPEVAR) {
            TypeVariable typeVar = (TypeVariable) type;
            if (typeVar.getUpperBound() != null) {
                return typeVar.getUpperBound();
            }
        } else if (type.getKind() == TypeKind.WILDCARD) {
            WildcardType wildcard = (WildcardType) type;
            if (wildcard.getExtendsBound() != null) {
                return wildcard.getExtendsBound();
            }
        }
        return type;
    }

    private boolean isValidField(VariableElement field) {
        return field.getAnnotation(Column.class) != null;
    }

    public void getVariable(TypeMirror typeMirror, List<VariableElement> fields, boolean deep) {
        try {
            typeMirror = normalize(typeMirror);
            if (typeMirror.getKind() == TypeKind.DECLARED) {
                DeclaredType declaredType = (DeclaredType) typeMirror;
                TypeElement e = (TypeElement) declaredType.asElement();
                // class
                if (e.getKind() == ElementKind.CLASS) {
                    if (e.getSuperclass().getKind() != TypeKind.NONE) {

                        String className = StrUtil.subBefore(typeMirror.toString(), "<", true);
                        TypeElement element = processingEnv.getElementUtils().getTypeElement(className);
                        if (element != null) {
                            java.util.List<? extends Element> elements = element.getEnclosedElements();
                            visitVariable(elements, fields);
                        }

                        if (deep) {
                            TypeMirror supertype = normalize(e.getSuperclass());
                            getVariable(supertype, fields, deep);
                        }
                    }
                }
            }
        } catch (Exception ex) {

        }


    }

    public void visitVariable(java.util.List<? extends Element> elements, List<VariableElement> fields) {
        for (VariableElement field : ElementFilter.fieldsIn(elements)) {
            if (isValidField(field)) {


                fields.add(field);
            }
        }
    }


}